1 /**
2  * This module implements functions to run the unittests with
3  * command-line options.
4  */
5 
6 module unit_threaded.runner;
7 
8 import unit_threaded.from;
9 
10 /**
11  * Runs all tests in passed-in modules. Modules can be symbols or
12  * strings. Generates a main function and substitutes the default D
13  * runtime unittest runner. This mixin should be used instead of
14  * $(D runTests) if a shared library is used instead of an executable.
15  */
16 mixin template runTestsMixin(Modules...) if (Modules.length > 0) {
17 
18     shared static this() {
19         import unit_threaded.testsuite : replaceModuleUnitTester;
20 
21         replaceModuleUnitTester;
22     }
23 
24     int main(string[] args) {
25         return runTests!Modules(args);
26     }
27 }
28 
29 /**
30  * Runs all tests in passed-in modules. Modules can be symbols
31  * or strings. Arguments are taken from the command-line.
32  * -s Can be passed to run in single-threaded mode. The rest
33  * of argv is considered to be test names to be run.
34  * Params:
35  *   args = Arguments passed to main.
36  * Returns: An integer suitable for the program's return code.
37  */
38 int runTests(Modules...)(string[] args) if (Modules.length > 0) {
39     import unit_threaded.reflection : allTestData;
40 
41     return runTests(args, allTestData!Modules);
42 }
43 
44 /**
45  * Runs all tests in passed-in testData. Arguments are taken from the
46  * command-line. `-s` Can be passed to run in single-threaded mode. The
47  * rest of argv is considered to be test names to be run.
48  * Params:
49  *   args = Arguments passed to main.
50  *   testData = Data about the tests to run.
51  * Returns: An integer suitable for the program's return code.
52  */
53 int runTests(string[] args, in from!"unit_threaded.reflection".TestData[] testData) {
54     import unit_threaded.options : getOptions;
55 
56     return runTests(getOptions(args), testData);
57 }
58 
59 int runTests(in from!"unit_threaded.options".Options options,
60         in from!"unit_threaded.reflection".TestData[] testData) {
61     import unit_threaded.testsuite : TestSuite;
62 
63     handleCmdLineOptions(options, testData);
64     if (options.exit)
65         return 0;
66 
67     auto suite = TestSuite(options, testData);
68     return suite.run ? 0 : 1;
69 }
70 
71 private void handleCmdLineOptions(in from!"unit_threaded.options".Options options,
72         in from!"unit_threaded.reflection".TestData[] testData) {
73 
74     import unit_threaded.io : enableDebugOutput, forceEscCodes;
75     import unit_threaded.testcase : enableStackTrace;
76     import std.algorithm : map;
77 
78     if (options.list) {
79         import std.stdio : writeln;
80 
81         writeln("Listing tests:");
82         foreach (test; testData.map!(a => a.name)) {
83             writeln(test);
84         }
85     }
86 
87     if (options.debugOutput)
88         enableDebugOutput();
89 
90     if (options.forceEscCodes)
91         forceEscCodes();
92 
93     if (options.stackTraces)
94         enableStackTrace();
95 }